<template>
  <div>
    <svg
      version="1.1"
      id="TMA"
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      x="0px"
      y="0px"
      :viewBox="isVertical ? GraphicData.viewBoxVertical : GraphicData.viewBox"
      class="container"
    >
      <!-- <defs>
        <filter id="f1" x="0" y="0">
          <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
        </filter>
      </defs> -->
      <!-- sectors -->
      <g id="content">
        <polygon
          v-for="(item, key, index) in GraphicData.content"
          :id="key"
          :points="joinPoints(item)"
          :class="['sector', sectorCodes.includes(key) ? 'sector-on' : '']"
        />
      </g>
      <!-- fixes -->
      <polygon
        v-for="(item, key, index) in GraphicData.fixes"
        :id="key"
        :points="`${item.x},${item.y + fixSize} ${item.x - fixSize},${item.y} ${
          item.x
        },${item.y - fixSize} ${item.x + fixSize},${item.y}`"
        class="fix"
      />
      <text
        v-for="(item, key, index) in GraphicData.fixes"
        :id="key"
        :transform="`matrix(1 0 0 1 ${item.x + fixSize * 1.5} ${
          item.y + fixSize * 1.5
        })`"
        class="fix-name"
      >
        {{ key }}
      </text>
      <!-- grids -->
      <g>
        <polygon
          v-for="(item, key, index) in grids.content"
          :id="key"
          :points="joinPoints(item)"
          :class="[
            'grid',
            nearbyGrids.includes(key)
              ? 'grid-near'
              : nearbyGrids2.includes(key)
              ? 'grid-near-2'
              : nearbyGrids3.includes(key)
              ? 'grid-near-3'
              : '',
          ]"
          :style="{
            // animationDelay: nearbyGrids.includes(key)
            //   ? getRandomNumber(0 - 15) * 50 + 'ms'
            //   : 0,
          }"
          @mouseenter="handleMouseEnter"
          @mouseleave="handleMouseLeave"
          @click="handleClick"
        />

        <!-- filter="url(#f1)" -->
      </g>
    </svg>
    <!-- <pre>{{ grids.range }}</pre> -->
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import useCommonStore from "@/store/common.js";
import GraphicData from "./GraphicData.json";
import useSeatStore from "@/store/seat.js";

const fixSize = ref(9);
const gridScale = 50;

const commonStore = useCommonStore();
const isVertical = computed(
  () =>
    commonStore.clientWidth -
      (commonStore.showSidebar ? commonStore.sidebarWidth : 0) <=
    commonStore.clientHeight
);

const joinPoints = (points) => {
  let string = "";
  points.forEach((point) => {
    string += `${point[0]},${point[1]} `;
  });
  return string.trim();
};

const grids = computed(() => {
  if (!GraphicData) return { range: null, content: {} };
  // generate range
  let minX = 999999;
  let minY = 999999;
  let maxX = 0;
  let maxY = 0;
  Object.keys(GraphicData.content).forEach((key) => {
    let item = GraphicData.content[key];
    item.forEach((point) => {
      minX = Math.min(minX, point[0]);
      minY = Math.min(minY, point[1]);
      maxX = Math.max(maxX, point[0]);
      maxY = Math.max(maxY, point[1]);
    });
  });
  const range = [
    [minX, minY],
    [maxX, maxY],
  ];
  // generate grids
  const content = {};
  let countX = 0;
  for (let x = minX - gridScale / 2; x < maxX; x += gridScale) {
    let countY = 0;
    for (let y = minY - gridScale / 2; y < maxY; y += gridScale) {
      content[`G_${countX}_${countY}`] = [
        [x, y],
        [x + gridScale, y],
        [x + gridScale, y + gridScale],
        [x, y + gridScale],
      ];
      countY++;
    }
    countX++;
  }
  return { range, content };
});

const emits = defineEmits(["gridClick", "gridHover"]);

const nearbyGrids = ref([]);
const nearbyGrids2 = ref([]);
const nearbyGrids3 = ref([]);

const handleMouseEnter = (e) => {
  const gridId = e.target.id;
  const coordinate = getCoordinate(gridId);
  nearbyGrids.value = [
    // 上下左右
    getGridId({ x: coordinate.x - 1, y: coordinate.y }),
    getGridId({ x: coordinate.x + 1, y: coordinate.y }),
    getGridId({ x: coordinate.x, y: coordinate.y - 1 }),
    getGridId({ x: coordinate.x, y: coordinate.y + 1 }),
  ];
  nearbyGrids2.value = [
    // 四个角
    getGridId({ x: coordinate.x - 1, y: coordinate.y - 1 }),
    getGridId({ x: coordinate.x - 1, y: coordinate.y + 1 }),
    getGridId({ x: coordinate.x + 1, y: coordinate.y - 1 }),
    getGridId({ x: coordinate.x + 1, y: coordinate.y + 1 }),
  ];

  nearbyGrids3.value = [
    // 第二圈
    getGridId({ x: coordinate.x + 2, y: coordinate.y }),
    getGridId({ x: coordinate.x, y: coordinate.y + 2 }),
    getGridId({ x: coordinate.x - 2, y: coordinate.y }),
    getGridId({ x: coordinate.x, y: coordinate.y - 2 }),
    getGridId({ x: coordinate.x + 1, y: coordinate.y - 2 }),
    getGridId({ x: coordinate.x - 1, y: coordinate.y - 2 }),
    getGridId({ x: coordinate.x + 1, y: coordinate.y + 2 }),
    getGridId({ x: coordinate.x - 1, y: coordinate.y + 2 }),
    getGridId({ x: coordinate.x - 2, y: coordinate.y - 1 }),
    getGridId({ x: coordinate.x - 2, y: coordinate.y + 1 }),
    getGridId({ x: coordinate.x + 2, y: coordinate.y - 1 }),
    getGridId({ x: coordinate.x + 2, y: coordinate.y + 1 }),
  ];
};

const handleMouseLeave = () => {
  nearbyGrids.value = [];
  nearbyGrids2.value = [];
  nearbyGrids3.value = [];
};

const handleClick = (e) => {
  const gridId = e.target.id;
  const coordinate = getCoordinate(gridId);
  const mousePosition = { x: e.clientX, y: e.clientY };
  const payload = { gridId, coordinate, mousePosition };
  emits("gridClick", payload);
};

const getCoordinate = (gridId) => {
  let item = gridId.split("_");
  return {
    x: Number(item[1]),
    y: Number(item[2]),
  };
};

const getGridId = (coordinate) => {
  return `G_${coordinate.x}_${coordinate.y}`;
};

function getRandomNumber(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

const seatStore = useSeatStore();

const sectorCodes = computed(() => {
  let seatContent = seatStore.seatStatus.filter(
    (seat) => seat.seatName == seatStore.currentSeat.seatName
  );
  if (seatContent.length > 0) {
    return seatContent[0].sectorCodes;
  }
  return [];
});
</script>

<style scoped>
.grid {
  fill: var(--el-text-color-primary);
  fill-opacity: 0;
  transition: all 0.2s ease-in-out;
  cursor: cell;
  /* stroke: #0000; */
  /* stroke-miterlimit: 10; */
}

.grid:hover {
  fill-opacity: 1;
  /* fill: var(--el-text-color-primary); */
  /* stroke: var(--el-text-color-secondary); */
  /* stroke-miterlimit: 10; */
  /* animation: breath 0.3s ease-in-out infinite alternate; */
}

@keyframes breath {
  0% {
    fill-opacity: 0.5;
  }
  100% {
    fill-opacity: 1;
  }
}

.grid-near {
  fill-opacity: 0.3;
  transition: all 0.4s ease-in-out;
  /* animation: breath-near 0.4s ease-in-out infinite alternate; */
}

@keyframes breath-near {
  0% {
    fill-opacity: 0;
  }
  100% {
    fill-opacity: 0.3;
  }
}

.grid-near-2 {
  fill-opacity: 0.2;
  transition: all 0.6s ease-in-out;
  /* animation: breath-near-2 0.6s ease-in-out infinite alternate; */
}

@keyframes breath-near-2 {
  0% {
    fill-opacity: 0;
  }
  100% {
    fill-opacity: 0.2;
  }
}

.grid-near-3 {
  fill-opacity: 0.1;
  transition: all 0.8s ease-in-out;
  /* animation: breath-near-3 0.8s ease-in-out infinite alternate; */
}

@keyframes breath-near-3 {
  0% {
    fill-opacity: 0;
  }
  100% {
    fill-opacity: 0.1;
  }
}

.sector {
  fill: var(--el-color-info-light-5);
  fill-opacity: 1;
  stroke: var(--el-color-info-light-5);
  stroke-miterlimit: 10;
}

.sector-on {
  fill: var(--el-color-info-light-3);
  fill-opacity: 1;
  stroke: var(--el-color-info-light-3);
  stroke-miterlimit: 10;
}

.fix {
  fill: var(--el-color-primary);
  fill-opacity: 1;
}

.fix-name {
  fill: var(--el-color-primary);
  font-family: "Consolas", "Courier New", Courier, monospace;
  font-size: 20px;
  font-weight: bolder;
}

.container {
  background-color: transparent;
  /* background-color: var(--el-color-info-light-8); */
}
</style>
